#!/bin/sh -ef
#
# Copyright (C) 2003-2019  Dmitry V. Levin <ldv@altlinux.org>
# 
# Run specified program within hasher chroot.
#
# SPDX-License-Identifier: GPL-2.0-or-later
#

x11_forwarding=
x11_timeout=60

. hsh-sh-functions

[ "${PROG%._}" = hsh-shell ] &&
	i_am_hsh_run= ||
	i_am_hsh_run=1

show_help()
{
	if [ -n "$i_am_hsh_run" ]; then
		cat <<EOF
hsh-run - run specified program within hasher chroot.

Usage: $PROG [options] [<path-to-workdir>] <program> [args]

<path-to-workdir> must be valid hasher directory.
EOF
	else
		cat <<EOF
hsh-shell - run shell within hasher chroot.

Usage: $PROG [options] [<path-to-workdir>]

<path-to-workdir> must be valid hasher directory.
EOF
	fi
	cat <<EOF

Options:
  --builder                 run program as builder;
EOF
	[ -z "$i_am_hsh_run" ] ||
		cat <<EOF
  --execute=PATH            copy given script to workdir and execute it;
EOF
	cat <<EOF
  --hasher-priv-dir=DIR     hasher-priv directory;
  --mountpoints=LIST        comma-separated list of mount points;
  --number=NUMBER           subconfig identifier;
EOF
	[ -z "$i_am_hsh_run" ] ||
		cat <<EOF
  --pty                     redirect standard descriptors to controlling pty;
EOF
		cat <<EOF
  --rooter                  run program as pseudoroot;
  --shell[=SHELL]           run interactive shell;
  --wait-lock               wait for workdir and hasher-priv locks;
  --no-wait-lock            do not wait for workdir and hasher-priv locks;
  --x11-timeout=SECONDS     how long X11 authorization will be valid;
  -x                        disable X11 forwarding;
  -X                        enable X11 forwarding;
  -Y                        enable trusted X11 forwarding;
  -q, --quiet               try to be more quiet;
  -v, --verbose             print a message for each action;
  -V, --version             print program version and exit;
  -h, --help                show this text and exit.
    
Report bugs to http://bugs.altlinux.ru/

EOF
	exit
}

TEMP=`getopt -n $PROG -o x,X,Y,$getopt_common_opts -l builder,${i_am_hsh_run:+execute:,}hasher-priv-dir:,mountpoints:,no-lock,number:,${i_am_hsh_run:+pty,}rooter,save-fakeroot,shell::,wait-lock,no-wait-lock,x11-timeout:,$getopt_common_longopts -- "$@"` ||
	show_usage
eval set -- "$TEMP"

run_as_rooter=
run_script=
run_shell=
shell_prog=bash

if [ -z "$i_am_hsh_run" ]; then
	run_shell=1
	use_pty=yes
	export use_pty
fi

while :; do
	case "$1" in
		--builder) run_as_rooter=
			;;
		--execute)
			run_script="$(opt_check_read "$1" "$2")"
			shift
			;;
		--hasher-priv-dir)
			hasher_priv_dir="$(opt_check_dir "$1" "$2")"
			shift
			;;
		--mountpoints) shift; requested_mountpoints="$1"
			;;
		--no-lock) no_lock=1
			;;
		--number)
			number="$(opt_check_number_ge_0 "$1" "$2")"
			shift
			;;
		--pty) use_pty=yes; export use_pty
			;;
		--rooter) run_as_rooter=1
			;;
		--save-fakeroot) message "Warning: obsolete option $1 ignored."
			;;
		--shell)
			run_shell=1
			use_pty=yes; export use_pty
			shift
			[ -z "$1" ] || shell_prog="$1"
			;;
		--wait-lock) lock_nowait=
			;;
		--no-wait-lock) lock_nowait=1
			;;
		--x11-timeout) shift; x11_timeout="$1"
			;;
		-x) x11_forwarding=
			;;
		-X) x11_forwarding=untrusted
			;;
		-Y) x11_forwarding=trusted
			;;
		--) shift; break
			;;
		*) parse_common_option "$1"
			;;
	esac
	shift
done

if [ -z "$workdir" ]; then
	# At least one argument.
	[ "$#" -ge 1 ] || show_usage 'Insufficient arguments.'
fi

if [ -z "$workdir" -o -d "${1:-}" ]; then
	set_workdir "${1:-}"
	shift
else
	set_workdir
fi

if [ -n "$run_script" -a -n "$run_shell" ]; then
	show_usage '--execute and --shell are mutually exclusive options.'
fi

if [ -n "$run_shell" ]; then
	[ "$#" -eq 0 ] || show_usage 'Too many arguments.'
	set -- -a "-$shell_prog" "$shell_prog"
fi

# Either --execute or one more argument, please.
[ "$#" -ge 1 -o -n "$run_script" ] ||
	show_usage 'Insufficient arguments.'

lock_workdir
[ -d "$chroot" ] || fatal "$chroot: cannot find chroot."
deduce_lock_hasher_priv

prepare_x11_forwarding || x11_forwarding=

[ -z "$run_script" ] ||
	install -pm755 $verbose "$run_script" "$chroot/.host/hsh-run" >&2

if [ -n "$run_as_rooter" ]; then
	create_entry_fakeroot_header
else
	create_entry_header
fi

cat >>"$entry" <<__EOF__
exec ${run_script:+/.host/hsh-run} $(for n; do printf %s "\"$(quote_shell "$n")\" "; done)
__EOF__

export requested_mountpoints

if [ -n "$run_as_rooter" ]; then
	chrootuid1
else
	chrootuid2
fi
